﻿using SimpleTerminal.Common;
using SimpleTerminal.Controls;
using SimpleTerminal.Forms;
using SimpleTerminal.Library;
using SimpleTerminal.Render;
using SimpleTerminal.Session;
using SimpleTerminal.TerminalControl;
using Renci.SshNet.Common;
using System;
using System.Collections;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Timers;
using System.Windows.Forms;
using static SimpleTerminal.Controls.TabLayout;
using static SimpleTerminal.Session.IConnection;
using Win32;
using System.Collections.Generic;

namespace SimpleTerminal
{
    public partial class MainForm : NiceForm
    {

        //ArrayList sessionsTable = new ArrayList();
        Hashtable Sessions = new Hashtable();

        Session activeSession;
        private string StartupId = null;

        public enum SessionState
        {
            StartupPage,
            Idle,
            Connecting,
            Connected,
            Disconnecting,
            Disconnected,
        };


        public class Session
        {
            public int tabLayoutIndex = 0;
            public Terminal terminal;
            public IConnection connection;
            public SessionState state = SessionState.Idle;
            public bool autoConnect = false;
            private string name;
            public string Id;

            public string Name
            {
                get => name; set
                {
                    name = value;
                    NameChanged?.Invoke(this, EventArgs.Empty);
                }
            }

            public EventHandler NameChanged;
        }

        private void SetConnectionEvent(IConnection connection)
        {
            connection.Connected += Session_Connected;
            connection.Disconnected += Session_Disconnected;
            connection.DataReceived += Session_DataReceived;
            connection.Error += Session_Error;
            connection.Connecting += Session_Connecting;
        }

        public IConnection CreateSSHConnection(string host, int port, string user, string pass)
        {
            SshConnection sshConnection = new SshConnection(host, port, user, pass);
            //session.HostKeyReceived += HostKeyReceived;
            SetConnectionEvent(sshConnection);
            return sshConnection;
        }

        public IConnection CeateSerialConnection(string portName, int baudRate, int dateBits, string parity, string stopBits)
        {
            SerialConnection serialConnection = new SerialConnection(portName, baudRate, dateBits, parity, stopBits);
            SetConnectionEvent(serialConnection);
            return serialConnection;
        }

        private void HostKeyReceived(object sender, HostKeyEventArgs e)
        {
            e.CanTrust = true;
            Console.WriteLine("HostKeyReceived");
        }

        protected void Session_Connecting(IConnection connection, ConnectingEventArgs args)
        {
            Invoke((EventHandler)delegate
            {
                if (!Sessions.ContainsKey(connection.Tag))
                    return;
                Session session = Sessions[connection.Tag] as Session;
                session.state = SessionState.Connecting;
                Terminal_Command(session, "Connecting to " + args.ConnectName + ". ");
            });
        }

        private void Session_Error(IConnection connection, SimpleTerminal.Session.ErrorEventArgs args)
        {
            this.Invoke((EventHandler)delegate
            {
                if (!Sessions.ContainsKey(connection.Tag))
                    return;
                Session session = Sessions[connection.Tag] as Session;

                if (session.state == SessionState.Connected)
                {
                    connection.BeginDisconnect();
                }
                switch (args.Error)
                {
                    case Errors.CONNECT_ERROR:
                        Terminal_Command(session, args.Msg);
                        break;
                    case Errors.AUTH_ERROR:
                        Terminal_Command(session, "Authentication failed.");
                        break;
                    case Errors.WSAECONNREFUSED:
                        Terminal_Command(session, "Connection refused. ");
                        break;
                    default:
                        Windows.Error(args.Msg);
                        break;
                }
            });
        }

        private void Terminal_PrintWelcome(Session session)
        {
            string line = "─────────────────────────────────────────";
            int left = (session.terminal.GetDisplayColumns() - line.Length - 2) / 2;
            StringBuilder leftSpaces = new StringBuilder();
            for (int i = 0; i < left; i++)
            {
                leftSpaces.Append(" ");
            }
            string sp = leftSpaces.ToString();
            string nl = "\r\n";
            string t_t = "\x1b[34m" + line + "\x1b[0m";
            string t_lt = "\x1b[34m┌\x1b[0m";
            string t_rt = "\x1b[34m┐\x1b[0m";
            string t_lb = "\x1b[34m└\x1b[0m";
            string t_rb = "\x1b[34m┘\x1b[0m";
            string t_ll = "\x1b[34m│\x1b[0m";
            string bs = "\x1b[K\x1b[0m\x1b[" + (session.terminal.GetDisplayColumns() - left) + "G\x1b[34m│\x1b[0m\x1b[K" + nl;

            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append(sp + t_lt + t_t + t_rt + nl);
            stringBuilder.Append(sp + t_ll + " \x1b[33m 欢迎使用 ⎣ SimpleTerminal ⎤\x1b[0m" + bs);
            stringBuilder.Append(sp + t_ll + bs);
            stringBuilder.Append(sp + t_ll + " \x1b[1;32m✔ 已支持SSH\x1b[0m\x1b[" + bs);
            stringBuilder.Append(sp + t_ll + " \x1b[1;32m✔ 已支持串口\x1b[0m" + bs);
            stringBuilder.Append(sp + t_ll + " \x1b[1;31m✘ 暂不支持SFTP\x1b[0m" + bs);
            stringBuilder.Append(sp + t_ll + " \x1b[1;31m✘ 本软件目前处于开发阶段,\x1b[0m" + bs);
            stringBuilder.Append(sp + t_ll + " \x1b[1;31m  请勿用于生产环境\x1b[0m" + bs);
            stringBuilder.Append(sp + t_ll + bs);
            stringBuilder.Append(sp + t_ll + " \x1b[1;34m★ 作者邮箱‹ zhendongdong@foxmail.com ›\x1b[0m" + bs);
            stringBuilder.Append(sp + t_lb + t_t + t_rb);
            /// for (int i = 0; i < session.terminal.GetDisplayColumns(); i++)
            // {
            //     stringBuilder.Append("—");
            // }
            stringBuilder.Append("\x1b[m\r\n");
            session.terminal.Input(Encoding.UTF8.GetBytes(stringBuilder.ToString()));
        }

        private void Terminal_Splite(Session session)
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append("\r\n\x1b[38;5;6;7;13m");
            for (int i = 0; i < session.terminal.GetDisplayColumns(); i++)
            {
                stringBuilder.Append("—");
            }
            stringBuilder.Append("\x1b[m\r\n");
            session.terminal.Input(Encoding.UTF8.GetBytes(stringBuilder.ToString()));
        }
        private void Terminal_Command(Session session, string text)
        {
            Terminal_Command(session, text, true);
        }

        private void Terminal_Command(Session session, string text, bool br)
        {
            if (session == null)
                return;
            string PS1 = (br ? "\r\n" : "") + "\x1b[1;32mTerminal : \x1b[m" + text + "";
            session.terminal.Input(Encoding.UTF8.GetBytes(PS1));
        }



        public MainForm()
        {
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            InitializeComponent();
            AutoScaleMode = AutoScaleMode.Dpi;
            //  SetClassLong(Handle, GCL_STYLE, GetClassLong(Handle, GCL_STYLE) | CS_DropSHADOW); //API函数加载，实现窗体边框阴影效果

            //this.tabLayout1.Clear();
            tabLayoutGroup.SelectChanged += TabLayout_SelectChanged;
            tabLayoutGroup.TabClosing += TabLayout_TabClosing;
            tabLayoutGroup.TabCreated += TabLayout_TabCreated;
            //toolStrip1.RenderMode = ToolStripRenderMode.Custom;
            toolStrip1.Renderer = new ToolStripMenuRender();
            menuStrip1.Renderer = new MenuStripMenuFatRender();
            contextMenuStrip.Renderer = new ToolStripSimpleRender();



            keepAliveTimer.Interval = 30000;
            keepAliveTimer.Enabled = true;
            keepAliveTimer.Elapsed += new ElapsedEventHandler(KeepAliveMessageTimer);
            keepAliveTimer.AutoReset = true;

            //SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, NULL, 0);

            // ControlBox = false;

            //  (new BytesToUCS()).Test();
            //SetTheme(new Theme {
            //    BackgroundColor = Color.FromArgb(251, 114, 153),
            //   ForegroundColor = Color.FromArgb(255, 255, 255),
            //});

            maxnumsizeBox.MouseEnter += delegate
            {
                maxnumsizeBox.BackColor = Color.White;
            };
            maxnumsizeBox.MouseLeave += delegate
            {

                maxnumsizeBox.BackColor = Color.Transparent;
            };
            maxnumsizeBox.Click += delegate
            {
                if (WindowState == FormWindowState.Normal)
                {
                    this.WindowState = FormWindowState.Maximized;
                    // maxnumsizeBox.Image = Properties.Resources.windows_re_b;
                }
                else if (WindowState == FormWindowState.Maximized)
                {
                    this.WindowState = FormWindowState.Normal;
                }
            };
            this.FormClosing += delegate
            {
                shadow.Close();
            };

            minimumSizeBox.MouseEnter += delegate
            {
                minimumSizeBox.BackColor = Color.White;
            };
            minimumSizeBox.MouseLeave += delegate
            {
                minimumSizeBox.BackColor = Color.Transparent;
            };
            minimumSizeBox.Click += delegate
            {
                this.WindowState = FormWindowState.Minimized;
            };
            closeBox.MouseEnter += delegate
            {
                closeBox.BackColor = Color.Red;
                closeBox.Image = Properties.Resources.windows_close_w;
            };
            closeBox.MouseLeave += delegate
            {
                closeBox.Image = Properties.Resources.windows_close_b;
                closeBox.BackColor = Color.Transparent;
            };
            closeBox.Click += delegate
            {
                this.Close();
            };
            //  FormBorderStyle = FormBorderStyle.None;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            shadow = new Shadow(this)
            {
                ShowInTaskbar = false
            };
            shadow.Show(this);
            CreateStartupPage();

            Update();


        }


        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            if (WindowState == FormWindowState.Normal)
            {
                maxnumsizeBox.Image = Properties.Resources.windows_max_b;
            }
            else if (WindowState == FormWindowState.Maximized)
            {
                maxnumsizeBox.Image = Properties.Resources.windows_re_b;
            }
        }


        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case 0x0219:
                    if (m.WParam.ToInt32() == 0x8004)//usb串口
                    {
                        KeepAliveMessageProcess(false);
                    }
                    break;
            }
            base.WndProc(ref m);
        }


        private readonly System.Timers.Timer keepAliveTimer = new System.Timers.Timer();
        private readonly object _keepAliveTimerLock = new object();

        private void KeepAliveMessageTimer(object sender, ElapsedEventArgs e)
        {
            KeepAliveMessageProcess(true);
        }
        private void KeepAliveMessageProcess(bool all)
        {
            lock (_keepAliveTimerLock)
            {
                foreach (Session session in Sessions.Values)
                {
                    if (session.state != SessionState.Connected)
                        continue;

                    if (!all && session.connection.GetSessionType() != SessionType.Serial)
                        continue;

                    if (!IsSessionConnected(session))
                        session.connection.BeginDisconnect();
                    else
                        session.connection.SendKeepAlive();
                }
            }
        }

        private void Form2_Paint(object sender, PaintEventArgs e)
        {
        }




        private void UpdateStatusBar()
        {
            if (activeSession == null)
            {
                statusLabelState.Text = "未就绪";
                return;
            }

            switch (activeSession.state)
            {
                case SessionState.StartupPage:
                    statusLabelState.Text = "启动页";
                    break;
                case SessionState.Idle:
                    statusLabelState.Text = "未就绪";
                    break;
                case SessionState.Connecting:
                    statusLabelState.Text = "连接中";
                    break;
                case SessionState.Connected:
                    statusLabelState.Text = "已连接";
                    break;
                case SessionState.Disconnecting:
                    statusLabelState.Text = "断开中";
                    break;
                case SessionState.Disconnected:
                    statusLabelState.Text = "已断开";
                    break;
            }

            //窗口尺寸
            if (activeSession.terminal != null)
            {
                toolStripStatusConsoleSize.Text = activeSession.terminal.GetDisplayColumns() +
                    " x " + activeSession.terminal.GetDisplayRows();
                fontStatusLabel.Text = activeSession.terminal.Font.Name + " "
                    + activeSession.terminal.Font.SizeInPoints + "pt";
            }
            else
            {
                toolStripStatusConsoleSize.Text = "";
                fontStatusLabel.Text = "";
            }
        }

        /// <summary>
        /// 创建一个控制台控件
        /// </summary>
        /// <returns></returns>
        private Terminal CreateTerminal()
        {
            Terminal terminal = new Terminal();
            (terminal as System.ComponentModel.ISupportInitialize).BeginInit();
            // terminal.
            terminal.BackColor = Preference.Default.Terminal_BackColor;
            terminal.Font = Preference.Default.Terminal_Font;
            terminal.ForeColor = Preference.Default.Terminal_ForeColor;
            terminal.Location = new Point(0, 0);
            terminal.TabStop = true;
            terminal.ImeMode = ImeMode.On;
            terminal.TabIndex = 0;
            terminal.Dock = DockStyle.Fill;
            terminal.ScrollBackSize = Preference.Default.Terminal_ScrollBackSize;
            terminal.CursorBackColor = Preference.Default.Terminal_CursorColor;
            terminal.CursorTextColor = Preference.Default.Terminal_CursorTextColor;
            terminal.Name = "Terminal";
            terminal.Text = "Terminal";
            terminal.KeyDown += Terminal_KeyDown;
            terminal.KeyPress += Terminal_KeyPress;
            terminal.KeyUp += Terminal_KeyUp;
            terminal.TerminalSizeChanged += Terminal_SizeChanged;
            terminal.TerminalOnLoaded += Terminal_OnLoaded;
            terminal.OnMouseReport += Terminal_MouseReport;
            terminal.MouseDown += Terminal_OnMouseDown;
            terminal.GotFocus += Terminal_GotFocus;
            terminal.FontChanged += Terminal_FontChanged;
            using (Datastore datastore = new Datastore())
            {
                List<Keyword> Keywords = datastore.Keywords();

                terminal.Keywords = Keywords;
            }
            (terminal as System.ComponentModel.ISupportInitialize).EndInit();
            return terminal;
        }


        protected void Terminal_FontChanged(object sender, EventArgs e)
        {
            UpdateStatusBar();
        }
        protected void Terminal_GotFocus(object sender, EventArgs e)
        {
            //Console.WriteLine("Terminal_GotFocus");
            Session session = Sessions[((Terminal)sender).Tag] as Session;
            activeSession = session;
            UpdateStatusBar();
        }
        protected void Terminal_OnMouseDown(object sender, MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (e.Button == MouseButtons.Right)
            {
                switch (Preference.Default.MouseRightClick)
                {
                    case 0:
                        contextMenuStrip.Show((Control)sender, e.Location);
                        break;
                    case 1:
                        MenuItemCopy_Click(this, e); ;
                        break;
                }
            }
        }


        private Session CreateSession(string name, IConnection connection)
        {
            return CreateSession(name, connection, SessionState.Idle);
        }
        private Session CreateSession(string name, IConnection connection, SessionState state)
        {

            string id = Guid.NewGuid().ToString();
            Terminal terminal = CreateTerminal();
            Session session = new Session
            {
                Id = id,
                Name = name,
                terminal = terminal,
                connection = connection,
                state = state
            };
            if (connection != null)
                connection.Tag = id;
            terminal.Tag = id;
            return session;

        }

        public void OnConnected(Session session)
        {
            session.state = SessionState.Connected;
        }



        private void CreateStartupPage()
        {
            Session session = CreateSession("启动页", null, SessionState.StartupPage);
            Sessions.Add(session.Id, session);
            StartupId = session.Id;
            PageContainer pageContainer = CreatePageContainer(session.terminal, session.Name, session.Id);
            session.NameChanged = delegate
            {
                pageContainer.Text = session.Name;
            };
            tabLayoutGroup.AddItem(pageContainer);
        }

        private IConnection CreateConnection(object connectionInfo)
        {
            if (connectionInfo is ProfileInfo)
            {
                return CreateConnection(connectionInfo as ProfileInfo);
            }
            else if (connectionInfo is SerialConnectionInfo)
            {
                return CreateConnection(connectionInfo as SerialConnectionInfo);
            }
            return null;
        }
        private IConnection CreateConnection(ProfileInfo connectionInfo)
        {
            SshConnection sshConnection = new SshConnection(connectionInfo.Host,
                connectionInfo.Port, connectionInfo.Account, connectionInfo.Password);
            //session.HostKeyReceived += HostKeyReceived;
            sshConnection.Name = connectionInfo.Name;
            SetConnectionEvent(sshConnection);
            return sshConnection;

        }

        private IConnection CreateConnection(SerialConnectionInfo connectionInfo)
        {
            SerialConnection serialConnection = new SerialConnection(connectionInfo.PortName,
                connectionInfo.BaudRate, connectionInfo.DateBits, connectionInfo.Parity, connectionInfo.StopBits);
            SetConnectionEvent(serialConnection);
            serialConnection.Name = connectionInfo.PortName;
            return serialConnection;
        }
        private void CreateTabPage(object connectionInfo)
        {
            IConnection connection;
            Session session;

            connection = CreateConnection(connectionInfo);
            if (StartupId != null)
            {
                session = Sessions[StartupId] as Session;
                StartupId = null;
                session.Name = connection.Name;
                session.connection = connection;
                connection.Tag = session.Id;
                session.state = SessionState.Idle;
                session.NameChanged = null;
                Session_Connect(session);
                Session_UpdateCount();
                UpdateStatusBar();
            }
            else
            {
                session = CreateSession(connection.Name, connection);
                Sessions.Add(session.Id, session);
                PageContainer pageContainer = CreatePageContainer(session.terminal, session.Name, session.Id);
                tabLayoutGroup.AddItem(pageContainer);
            }
        }

        private PageContainer CreatePageContainer(Control control, string name, string id)
        {
            PageContainer tabLayoutItem = new PageContainer(control)
            {
                Text = name,
                Tag = id,
                Name = id,
            };

            tabLayoutItem.Controls.Add(control);
            return tabLayoutItem;
        }

        private void TabLayout_TabCreated(object sender, TabEventArgs e)
        {
            Session session = Sessions[e.Item.Tag] as Session;
            // Log.Debug("MainForm", "TabLayout_TabCreated");
            if (session.state == SessionState.StartupPage)
            {
                Terminal_PrintWelcome(session);
            }
            else if (session.state == SessionState.Idle)
            {
                Session_Connect(session);
            }
            Session_UpdateCount();
            UpdateStatusBar();
        }
        private void TabLayout_SelectChanged(object sender, TabEventArgs e)
        {
            // Console.WriteLine(e.Item.Tag.ToString());
            // Session session = ConvertToSession(e.Item);
            // activeSession = session;
            // UpdateState();
        }
        private void TabLayout_TabClosing(object sender, TabEventArgs e)
        {
            //if (!(e.Item is Session session))
            //    return;
            Session session = Sessions[e.Item.Tag] as Session;
            if (session.state != SessionState.StartupPage)
            {
                if (session.state == SessionState.Connecting
                                || session.state == SessionState.Connected)
                {
                    session.connection.Disconnect();
                }
                session.terminal.Close();
            }
            Sessions.Remove(e.Item.Tag);
            if (Sessions.Count == 0)
            {
                activeSession = null;
            }
            Session_UpdateCount();
            UpdateStatusBar();
        }

        private void Session_Connect(Session session)
        {
            Terminal terminal = session.terminal;
            session.connection.TerminalName = "xterm";
            session.connection.Columns = (uint)terminal.GetDisplayColumns();
            session.connection.Rows = (uint)terminal.GetDisplayRows();
            session.connection.Width = (uint)terminal.Width;
            session.connection.Height = (uint)terminal.Height;
            session.state = SessionState.Connecting;
            session.connection.BeginConnect();
        }

        /// <summary>
        /// Terminal控件被成功创建的时候执行此回调
        /// </summary>
        /// <param name="terminal"></param>
        private void Terminal_OnLoaded(Terminal terminal)
        {

        }


        /// <summary>
        /// Terminal的尺寸发生改变的时候执行此函数
        /// 应该在此函数中发送尺寸改变的消息到远端服务器
        /// 此函数不是实时执行，具有一定的延迟
        /// </summary>
        /// <param name="terminal"></param>
        private void Terminal_SizeChanged(Terminal terminal)
        {
            Invoke((EventHandler)delegate
            {
                Session session = Sessions[terminal.Tag] as Session;

                if (IsSessionConnected(session))
                {
                    SendWindowChangeRequest(session);
                }
                UpdateStatusBar();
            });
        }
        private void SendWindowChangeRequest(Session session)
        {
            session.connection.SendWindowChangeRequest(
                                   session.terminal.GetDisplayColumns(),
                                   session.terminal.GetDisplayRows(),
                                   session.terminal.Width,
                                   session.terminal.Height);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="clientSession"></param>
        private void Session_Connected(IConnection connection)
        {
            Invoke((EventHandler)delegate
            {
                if (!Sessions.ContainsKey(connection.Tag))
                    return;

                Session session = Sessions[connection.Tag] as Session;

                session.state = SessionState.Connected;
                Terminal_Command(session, "Connection established.");
                Terminal_Splite(session);

                tabLayoutGroup.Find(session.Id).Indicator = true;

                if (connection.Tag == ActiveConnection.Tag)
                {
                    UpdateStatusBar();
                }
                SendWindowChangeRequest(session);
            });
        }


        /// <summary>
        /// 会话（用户主动）断开后执行此方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Session_Disconnected(IConnection connection)
        {
            /*
             * 断开事件有可能是在子进程中执行的，因此必须以委托的方式运行
             */
            Invoke((EventHandler)delegate
            {
                if (!Sessions.ContainsKey(connection.Tag))
                    return;

                Session session = Sessions[connection.Tag] as Session;

                session.state = SessionState.Disconnected;
                Terminal_Command(session, "Connection closed! ");

                tabLayoutGroup.Find(session.Id).Indicator = false;


                /*
                 * 在autoConnect标志被设置的时候则重新连接 
                 * 例如在点击了 “重新连接”按钮的情况下。
                 */
                //connection.DataReceived -= Session_DataReceived;

                if (session.autoConnect)
                {
                    session.autoConnect = false;
                    Session_Connect(session);
                }

                UpdateStatusBar();

            });

        }

        /// <summary>
        /// 会话接收到数据后执行此方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Session_DataReceived(IConnection connection, DataEventArgs e)
        {
            if (!Sessions.ContainsKey(connection.Tag))
                return;
            Session session = Sessions[connection.Tag] as Session;
            session.terminal.Input(e.Data);
        }

        private void Session_UpdateCount()
        {
            int count = 0;
            foreach (Session session in Sessions.Values)
            {
                if (session.state != SessionState.StartupPage)
                    count++;
            }
            toolStripStatusSessionsCount.Text = "" + count + "个会话";
        }


        private bool IsSessionConnected(Session session)
        {
            if (session.state == SessionState.Connected &&
                session.connection != null &&
                session.connection.IsConnected())
                return true;
            return false;
        }

        private void SendEscSq(string op)
        {
            if (this.IsConnected)
            {
                string esc = ((char)'\x1b').ToString();
                if (ActiveTerminal.DECCKM)
                    esc += "O" + op;
                else
                    esc += "[" + op;
                ActiveConnection.Send(esc);
            }
        }

        private void Terminal_MouseReport(int keycode, int x, int y)
        {
            if (this.IsConnected)
                ActiveConnection.Send('\x1b'.ToString() + "[M" + ((char)keycode).ToString() + "" + ((char)x).ToString() + "" + ((char)y).ToString());
        }

        private void Terminal_KeyDown(object sender, KeyEventArgs e)
        {

            e.Handled = true;

            switch (e.KeyCode)
            {
                case Keys.Up:
                    SendEscSq("A");
                    break;
                case Keys.Down:
                    SendEscSq("B");
                    break;
                case Keys.Right:
                    SendEscSq("C");
                    break;
                case Keys.Left:
                    SendEscSq("D");
                    break;
                case Keys.Insert:
                    SendEscSq("2~");
                    break;
                case Keys.PageUp:
                    SendEscSq("5~");
                    break;
                case Keys.PageDown:
                    SendEscSq("6~");
                    break;
                case Keys.F1:
                    SendEscSq("11~");
                    break;
                case Keys.F2:
                    SendEscSq("12~");
                    break;
                case Keys.F3:
                    SendEscSq("13~");
                    break;
                case Keys.F4:
                    SendEscSq("14~");
                    break;
                case Keys.F5:
                    SendEscSq("15~");
                    break;
                case Keys.F6:
                    SendEscSq("17~");
                    break;
                case Keys.F7:
                    SendEscSq("18~");
                    break;
                case Keys.F8:
                    SendEscSq("19~");
                    break;
                case Keys.F9:
                    SendEscSq("20~");
                    break;
                case Keys.F10:
                    SendEscSq("21~");
                    break;
                case Keys.F11:
                    SendEscSq("23~");
                    break;
                case Keys.F12:
                    SendEscSq("24~");
                    break;
            }

        }


        private void Terminal_KeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled = true;
            if (!this.IsConnected)
                return;
            ActiveConnection.Send(e.KeyChar.ToString());

        }

        private void Terminal_KeyUp(object sender, KeyEventArgs e)
        {
            e.Handled = true;
        }

        private void OpenConnectCreateDialog()
        {
            ConnectInfo connect = new ConnectInfo
            {
                StartPosition = FormStartPosition.CenterScreen
            };
            connect.ShowDialog();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {

        }



        private bool IsConnected
        {
            get
            {
                return IsSessionConnected(activeSession);
            }
        }



        //菜单栏
        private void CreateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.OpenConnectCreateDialog();
        }



        //工具栏
        private void ToolBtnCreate_Click(object sender, EventArgs e)
        {
            //this.OpenConnectCreateDialog();
            SelectPort selectPort = new SelectPort
            {
                StartPosition = FormStartPosition.CenterParent
            };
            if (selectPort.ShowDialog() == DialogResult.OK)
            {
                CreateTabPage(selectPort.SerialConnectionInfo);
            }
        }



        private void MenuItemEdit_Click(object sender, EventArgs e)
        {
        }
        /// <summary>
        /// 当上下文菜单被打开的时候此函数被调用
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ContextMenuStrip1_Opening(object sender, System.ComponentModel.CancelEventArgs e)
        {
            menuItemDisconnect.Enabled = this.IsConnected;
            menuItemCopy.Enabled = ActiveTerminal.SelectRegionState;
            menuItemSearch.Enabled = ActiveTerminal.SelectRegionState;
            openWithNotepad_Region.Enabled = ActiveTerminal.SelectRegionState;

            if (ActiveTerminal.LogStarting)
            {
                menuItemStopLog.Enabled = false;
                menuItemStartLog.Enabled = true;
            }
            else
            {
                menuItemStopLog.Enabled = true;
                menuItemStartLog.Enabled = false;
            }
            menuItemOpenFileDir.Enabled = ActiveTerminal.LogPath != null &&
                ActiveTerminal.LogPath.Length > 0;


            if (ActiveConnection != null && ActiveConnection.Canwrite)
                menuItemLock.Image = Properties.Resources.unlock;
            else
                menuItemLock.Image = Properties.Resources._lock;

        }

        /// <summary>
        /// 点击复制的时候执行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void MenuItemCopy_Click(object sender, EventArgs e)
        {
            if (ActiveTerminal != null && ActiveTerminal.SelectRegionState)
            {
                Clipboard.SetDataObject(ActiveTerminal.SelectRegionText.Trim(), true);
            }
        }
        /// <summary>
        /// 点击上下文菜单中的粘贴时执行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void MenuItemPaste_Click(object sender, EventArgs e)
        {
            IDataObject iData = Clipboard.GetDataObject();
            ActiveTerminal.SelectRegionState = false;
            if (iData.GetDataPresent(DataFormats.Text))
            {
                string text = (string)iData.GetData(DataFormats.Text);
                if (!IsConnected)
                    return;
                ActiveConnection.Send(text);
            }
        }

        /// <summary>
        /// 点击上下文菜单中的清空屏幕时执行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void MenuItemClearAll_Click(object sender, EventArgs e)
        {
            ActiveTerminal.ClearAll();
        }

        /// <summary>
        /// 点击上下文菜单中的 搜索 时执行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void MenuItemSearch_Click(object sender, EventArgs e)
        {
            string text = ActiveTerminal.SelectRegionText.Trim();
            System.Diagnostics.Process.Start("http://www.baidu.com/s?wd=" + text);
        }

        /// <summary>
        /// 点击上下文菜单中的 断开连接 时执行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MenuItemDisconnect_Click(object sender, EventArgs e)
        {
            if (this.IsConnected)
                ActiveConnection.BeginDisconnect();
        }

        private void MenuItemEdit_DropDownOpened(object sender, EventArgs e)
        {

        }

        private void MenuItemEdit_DropDownOpening(object sender, EventArgs e)
        {
            if (ActiveTerminal != null)
                toolStripCopy.Enabled = ActiveTerminal.SelectRegionState;

        }

        // public bool Opened

        public IConnection ActiveConnection
        {
            get
            {
                if (activeSession == null)
                    return null;
                return activeSession.connection;
            }
        }

        public Terminal ActiveTerminal
        {
            get
            {
                if (activeSession == null)
                    return null;
                return activeSession.terminal;
            }
        }

        private void MenuLeftLabel_Click(object sender, EventArgs e)
        {
            tabLayoutGroup.ActivedTabLayout.SelectIndex--;
        }

        private void MenuRightLabel_Click(object sender, EventArgs e)
        {
            tabLayoutGroup.ActivedTabLayout.SelectIndex++;
        }

        private void MenuItemAbout_Click(object sender, EventArgs e)
        {
            AboutBox1 aboutBox1 = new AboutBox1
            {
                StartPosition = FormStartPosition.CenterParent
            };
            aboutBox1.ShowDialog();
        }

        private void ToolBtnReconnect_Click(object sender, EventArgs e)
        {
            if (ActiveConnection != null)
            {
                if (activeSession.state == SessionState.StartupPage)
                {
                    return;
                }
                if (activeSession.state == SessionState.Connecting
                    || activeSession.state == SessionState.Connected)
                {
                    //断开连接
                    activeSession.autoConnect = true;
                    ActiveConnection.BeginDisconnect();
                }
                else
                {
                    Session_Connect(activeSession);
                }

            }
        }

        private void ToolBtnOpen_Click(object sender, EventArgs e)
        {
            SelectProfileForm selectProfileForm = new SelectProfileForm();
            selectProfileForm.StartPosition = FormStartPosition.CenterParent;
            selectProfileForm.SelectedProfile += SelectProfileForm_SelectedProfile;
            selectProfileForm.ShowDialog();
        }

        private void SelectProfileForm_SelectedProfile(object sender, ProfileInfo profile)
        {
            this.BeginInvoke((EventHandler)delegate
            {
                this.CreateTabPage(profile);
            });
        }

        private void MenuItemPreference_Click(object sender, EventArgs e)
        {
            PreferenceForm preferenceForm = new PreferenceForm
            {
                StartPosition = FormStartPosition.CenterParent
            };
            if (preferenceForm.ShowDialog() == DialogResult.OK)
            {
                foreach (Session session in Sessions.Values)
                {
                    if (session.terminal == null)
                        continue;
                    session.terminal.SuspendLayout();
                    session.terminal.CursorBackColor = Preference.Default.Terminal_CursorColor;
                    session.terminal.CursorTextColor = Preference.Default.Terminal_CursorTextColor;
                    session.terminal.BackColor = Preference.Default.Terminal_BackColor;
                    session.terminal.ForeColor = Preference.Default.Terminal_ForeColor;
                    session.terminal.Font = Preference.Default.Terminal_Font;
                    session.terminal.ScrollBackSize = Preference.Default.Terminal_ScrollBackSize;
                    session.terminal.ResumeLayout(false);
                }
            }
        }

        private void ToolBtnSetting_Click(object sender, EventArgs e)
        {
            MenuItemPreference_Click(sender, e);
        }

        private void MainForm_Shown(object sender, EventArgs e)
        {
            if (Preference.Default.Startup_Open)
            {
                ToolBtnOpen_Click(sender, e);
            }
        }

        private void MenuItemClearScroll_Click(object sender, EventArgs e)
        {
            if (ActiveTerminal != null)
            {
                ActiveTerminal.ClearScrollBack();
            }
        }

        private void ToolBtnHelp_Click(object sender, EventArgs e)
        {

        }

        private void menuItemLock_Click(object sender, EventArgs e)
        {
            if (ActiveConnection != null)
                ActiveConnection.Canwrite = !ActiveConnection.Canwrite;
        }

        private void MenuItemOpenSerial_Click(object sender, EventArgs e)
        {
            ToolBtnCreate_Click(sender, e);
        }

        private void MenuItemUpgrade_Click(object sender, EventArgs e)
        {
            UpgradeForm upgradeForm = new UpgradeForm();
            upgradeForm.StartPosition = FormStartPosition.CenterParent;
            upgradeForm.ShowDialog();
        }

        private void OpenNotePad(string text)
        {
            System.Diagnostics.Process Proc;

            try
            {
                // 启动记事本
                Proc = new System.Diagnostics.Process();
                Proc.StartInfo.FileName = "notepad.exe";
                Proc.StartInfo.UseShellExecute = false;
                Proc.StartInfo.RedirectStandardInput = true;
                Proc.StartInfo.RedirectStandardOutput = true;

                Proc.Start();
            }
            catch
            {
                Proc = null;
            }
            if (Proc != null)
            {
                // 调用 API, 传递数据
                while (Proc.MainWindowHandle == IntPtr.Zero)
                {
                    Proc.Refresh();
                }

                IntPtr vHandle = User32.FindWindowEx(Proc.MainWindowHandle, IntPtr.Zero, "Edit", null);

                // 传递数据给记事本
                User32.SendMessageString(vHandle, User32.WM_SETTEXT, 0, text);
            }
        }

        private void OpenWithNotepad_Region_Click(object sender, EventArgs e)
        {
            OpenNotePad(ActiveTerminal.SelectRegionText);
        }

        private void OpenWithNotepad_Screen_Click(object sender, EventArgs e)
        {
            OpenNotePad(ActiveTerminal.ScreenText);
        }

        private void OpenWithNotepad_All_Click(object sender, EventArgs e)
        {
            OpenNotePad(ActiveTerminal.Text);
        }

        private void MenuItemOpenLog_Click(object sender, EventArgs e)
        {
            try
            {
                activeSession.terminal.StartLog(activeSession.Name);
            }
            catch (Exception exception)
            {
                Windows.Error(exception.Message);
            }
        }

        private void MenuItemStopLog_Click(object sender, EventArgs e)
        {

            activeSession.terminal.StopLog();
        }

        private void MenuItemOpenFileDir_Click(object sender, EventArgs e)
        {
            Process proc = new Process();
            proc.StartInfo.FileName = "explorer";
            //打开资源管理器
            proc.StartInfo.Arguments = @"/select," + activeSession.terminal.LogPath;
            proc.Start();

        }

        private void MenuItemResetCursor_Click(object sender, EventArgs e)
        {
            if (ActiveTerminal != null)
            {
                ActiveTerminal.SetCursorVisible(true);
                ActiveTerminal.UpdateUi();
            }
        }

        private void Panel2_MouseDown(object sender, MouseEventArgs e)
        {
            User32.ReleaseCapture();
            User32.SendMessage(Handle, 0x112, 0xf012, 0);
        }

        private void FullScreen()
        {
            if (WindowState == FormWindowState.Normal)
            {
                WindowState = FormWindowState.Maximized;
            }
            else
            {
                WindowState = FormWindowState.Normal;
            }
        }
        private void toolStripFullScreen_Click(object sender, EventArgs e)
        {
            FullScreen();
        }

        private void MenuItemFullScreen_Click(object sender, EventArgs e)
        {
            FullScreen();
        }

        private void TopMenuBar_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (this.WindowState == FormWindowState.Maximized)
                this.WindowState = FormWindowState.Normal;
            else
                this.WindowState = FormWindowState.Maximized;
        }

        private void KeywordToolStripMenuItem_Click(object sender, EventArgs e)
        {
            KeywordListForm keywordListForm = new KeywordListForm();
            keywordListForm.StartPosition = FormStartPosition.CenterScreen;
            keywordListForm.ShowDialog(this);
            using (Datastore datastore = new Datastore())
            {
                List<Keyword> Keywords = datastore.Keywords();
                foreach (Session session in Sessions.Values)
                {
                    if (session.terminal == null)
                        continue;
                    session.terminal.Keywords = Keywords;
                }

            }


        }
    }
}
